package com.smartdot.bluetoothidcarddemo.camera;

import android.app.Activity;
import android.graphics.ImageFormat;
import android.graphics.Matrix;
import android.graphics.RectF;
import android.hardware.Camera;
import android.os.SystemClock;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

import com.smartdot.bluetoothidcarddemo.utils.LogUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class CameraHelper {

    private Camera mCamera = null;//Camera对象
    private Camera.Parameters mParameters;//Camera对象的参数
    private SurfaceView mSurfaceView;//用于预览的SurfaceView对象
    private SurfaceHolder mSurfaceHolder;//SurfaceHolder对象

    private Activity mActivity;

    public static int mCameraFacing = Camera.CameraInfo.CAMERA_FACING_BACK; //摄像头方向
    int mDisplayOrientation = 0;    //预览旋转的角度

    private int picWidth = 2160;       //保存图片的宽
    private int picHeight = 3840;       //保存图片的高


    public interface CallBack {
        void onPreviewFrame(byte[] data, int[] parameter, Camera camera);

        void onTakePic(byte[] data, int[] parameter);

        void onFaceDetect(Camera.Face[] faces);
    }

    public void addCallBack(CallBack callBack) {
        this.mCallBack = callBack;
    }

    private CallBack mCallBack;

    public CameraHelper() {
        init();
    }

    public CameraHelper(Activity mActivity, SurfaceView mSurfaceView) {
        this.mActivity = mActivity;
        this.mSurfaceView = mSurfaceView;
        init();
    }

    public void takePic() {
        if (mCamera != null) {
            mCamera.takePicture(null, null, new Camera.PictureCallback() {
                @Override
                public void onPictureTaken(byte[] data, Camera camera) {
                    LogUtils.eNormal("luoli", "拍完照了 开启预览以及人脸检测");
                    mCamera.stopPreview();
                    int[] cameraDisplayOrientation = getCameraDisplayOrientation(mActivity);
                    mCallBack.onTakePic(data, cameraDisplayOrientation);
                }
            });
        }
    }

    private void startFaceDetect() {
        try {
            // 开启人脸检测
            mCamera.startFaceDetection();
            mCamera.setFaceDetectionListener(new Camera.FaceDetectionListener() {
                @Override
                public void onFaceDetection(Camera.Face[] faces, Camera camera) {

                    mCallBack.onFaceDetect(faces);
                }
            });
        } catch (Exception e) {
            LogUtils.eNormal("luoli", "此设备不支持硬件人脸检测");
        }

    }

    /**
     * 相机预览数据的回调
     */
    private Camera.PreviewCallback previewCallback = new Camera.PreviewCallback() {
        @Override
        public void onPreviewFrame(byte[] data, Camera camera) {
//            LogUtils.eNormal("luoli:预览数据",new String(data));
            int[] cameraDisplayOrientation = getCameraDisplayOrientation(mActivity);
            mCallBack.onPreviewFrame(data, cameraDisplayOrientation, camera);
        }
    };

    private void init() {
        mSurfaceHolder = mSurfaceView.getHolder();
        //缓存持有者 添加回传
        mSurfaceHolder.addCallback(callback);
    }

    /**
     * 切换摄像头
     */
    public void exchangeCamera() {
        releaseCamera();

        if (mCameraFacing == Camera.CameraInfo.CAMERA_FACING_BACK) {
            mCameraFacing = Camera.CameraInfo.CAMERA_FACING_FRONT;
        } else {
            mCameraFacing = Camera.CameraInfo.CAMERA_FACING_BACK;
        }

        getCamera(mCameraFacing);
        startPreview();
    }

    private SurfaceHolder.Callback callback = new SurfaceHolder.Callback() {
        @Override
        public void surfaceCreated(SurfaceHolder surfaceHolder) {
            /**surface第一次创建时回调*/
            //得到相机 初始化
            if (mCamera == null) {
                getCamera(mCameraFacing);
            }
            startPreview();
        }

        @Override
        public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
            /**surface变化的时候回调(格式/大小)*/
        }

        @Override
        public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
            /**surface销毁的时候回调*/
            //缓存销毁时 release释放
            //释放相机 以免再次使用相机出现被占用的现象
            releaseCamera();

        }
    };

    public void stopFaceDetection() {
        // 停止人脸检测
        if (mCamera != null) {
            mCamera.stopPreview();
            mCamera.stopFaceDetection();
        }
    }

    public void reStartFaceDetection() {
        try {
            if (mCamera != null) {
                // 开启人脸检测  开启前先关闭  防止二次开启报错
                mCamera.startPreview();
                mCamera.startFaceDetection();
            }
        } catch (Exception e) {
            e.printStackTrace();
            if (mCamera != null) {
                mCamera.startPreview();
                mCamera.stopFaceDetection();
                mCamera.startFaceDetection();
            }
        }
    }

    /**
     * 开启预览
     */
    private void startPreview() {

        try {
            //设置一个Surface对象用来实时预览
            mCamera.setPreviewDisplay(mSurfaceHolder);
            // 设置预览方向
            setCameraDisplayOrientation(mActivity);
            //开始预览
            mCamera.startPreview();
            SystemClock.sleep(1000);
            startFaceDetect();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //得到相机
    private boolean getCamera(int cameraFacing) {
        // 判断是否支持指定相机
        boolean supportCameraFacing = supportCameraFacing(cameraFacing);

        if (supportCameraFacing) {
            try {
                //打开相机 一般的手机上都有前后两个摄像头，那么后置摄像头id就是0，前置摄像头id就是1
                // Camera.open()使用当前设备上第一个后置摄像头创建一个Camera对象。如果当前设备没有后置摄像头，则返回值为null
                mCamera = Camera.open(cameraFacing);
                initParameters(mCamera);          //初始化相机配置信息

                // 设置相机预览数据的回调
                mCamera.setPreviewCallback(previewCallback);
            } catch (Exception ex) {
                // 打开相机失败
                return false;
            }
        }
        return supportCameraFacing;
    }

    //配置相机参数
    private void initParameters(Camera camera) {
        try {
            mParameters = camera.getParameters();
            mParameters.setPreviewFormat(ImageFormat.NV21);  //设置预览图片的格式

            //获取与指定宽高相等或最接近的尺寸
            //设置预览尺寸
            Camera.Size bestPreviewSize = getBestSize(mSurfaceView.getWidth(), mSurfaceView.getHeight(), mParameters.getSupportedPreviewSizes());
            if (bestPreviewSize != null) {
                mParameters.setPreviewSize(bestPreviewSize.width, bestPreviewSize.height);

            }

            //设置保存图片尺寸
            Camera.Size bestPicSize = getBestSize(picWidth, picHeight, mParameters.getSupportedPictureSizes());
            if (bestPicSize != null) {
                mParameters.setPictureSize(bestPicSize.width, bestPicSize.height);

            }

            //对焦模式
            if (isSupportFocus(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
                mParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
            }

            camera.setParameters(mParameters);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //获取与指定宽高相等或最接近的尺寸
    private Camera.Size getBestSize(int targetWidth, int targetHeight, List<Camera.Size> sizeList) {
        Camera.Size bestSize = null;
        int targetRatio = (targetHeight / targetWidth);  //目标大小的宽高比
        int minDiff = targetRatio;
        for (Camera.Size size : sizeList) {
            int supportedRatio = (size.width / size.height);
//            LogUtils.eNormal("luoli", "系统支持的尺寸 宽: " + size.width + "  高：" + size.height + "比例:" + supportedRatio);
        }
        for (Camera.Size size : sizeList) {
            if (size.width == targetHeight && size.height == targetWidth) {
                bestSize = size;
                break;
            }
            int supportedRatio = (size.width / size.height);
            if (Math.abs(supportedRatio - targetRatio) < minDiff) {
                minDiff = Math.abs(supportedRatio - targetRatio);
                bestSize = size;
            }
        }

//        LogUtils.eNormal("luoli", "目标尺寸 ：" + targetWidth + "*" + targetHeight + "   比例:" + targetRatio);
//        LogUtils.eNormal("luoli", "最优尺寸 ：" + bestSize.height + "*" + bestSize.width);
        return bestSize;
    }

    //设置预览旋转的角度
    private void setCameraDisplayOrientation(Activity activity) {
        Camera.CameraInfo info = new Camera.CameraInfo();
        Camera.getCameraInfo(mCameraFacing, info);
        int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();

        int screenDegree = 0;
        switch (rotation) {
            case Surface.ROTATION_0:
                screenDegree = 0;
                break;
            case Surface.ROTATION_90:
                screenDegree = 90;
                break;
            case Surface.ROTATION_180:
                screenDegree = 180;
                break;
            case Surface.ROTATION_270:
                screenDegree = 270;
                break;
        }

        if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            mDisplayOrientation = (info.orientation + screenDegree) % 360;
            mDisplayOrientation = (360 - mDisplayOrientation) % 360;         // compensate the mirror
        } else {
            mDisplayOrientation = (info.orientation - screenDegree + 360) % 360;
        }
        mCamera.setDisplayOrientation(mDisplayOrientation);

//        LogUtils.eNormal("luoli", "屏幕的旋转角度 : " + rotation);
//        LogUtils.eNormal("luoli", "setDisplayOrientation(result) : " + mDisplayOrientation);
    }


    //设置预览旋转的角度
    private int[] getCameraDisplayOrientation(Activity activity) {
        Camera.CameraInfo info = new Camera.CameraInfo();
        Camera.getCameraInfo(mCameraFacing, info);
        int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();

        int screenDegree = 0;
        switch (rotation) {
            case Surface.ROTATION_0:
                screenDegree = 0;
                break;
            case Surface.ROTATION_90:
                screenDegree = 90;
                break;
            case Surface.ROTATION_180:
                screenDegree = 180;
                break;
            case Surface.ROTATION_270:
                screenDegree = 270;
                break;
        }

        if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            mDisplayOrientation = (info.orientation + screenDegree) % 360;
            mDisplayOrientation = (360 - mDisplayOrientation) % 360;         // compensate the mirror
        } else {
            mDisplayOrientation = (info.orientation - screenDegree + 360) % 360;
        }
        return new int[]{rotation, mDisplayOrientation};
    }

    //判断是否支持某一对焦模式
    private Boolean isSupportFocus(String focusMode) {
        boolean autoFocus = false;
        List<String> listFocusMode = mParameters.getSupportedFocusModes();
        for (String s : listFocusMode) {
            if (s.equals(focusMode))
                autoFocus = true;
        }

        return autoFocus;
    }

    //判断是否支持某个相机
    private boolean supportCameraFacing(int cameraFacing) {
        Camera.CameraInfo info = new Camera.CameraInfo();
        int numberOfCameras = Camera.getNumberOfCameras();
        for (int i = 0; i < numberOfCameras; i++) {
            Camera.getCameraInfo(i, info);
            if (info.facing == cameraFacing)
                return true;
        }
        return false;
    }

    //release释放
    public void releaseCamera() {
        //如果相机不为空 释放相机   初始化
        if (mCamera != null) {
            mCamera.stopPreview();
            mCamera.stopFaceDetection();
            mCamera.setPreviewCallback(null);
            mCamera.setFaceDetectionListener(null);
            mCamera.release();
            mCamera = null;
        }
    }

    //将相机中用于表示人脸矩形的坐标转换成UI页面的坐标
    public ArrayList<RectF> transForm(Camera.Face[] faces) {
        Matrix matrix = new Matrix();
        boolean mirror = (mCameraFacing == Camera.CameraInfo.CAMERA_FACING_FRONT);
        float sx = 0;
        if (mirror) {
            sx = -1f;
        } else {
            sx = 1f;
        }
        matrix.setScale(sx, 1f);
        // This is the value for android.hardware.Camera.setDisplayOrientation.
        matrix.postRotate(mDisplayOrientation);
        // Camera driver coordinates range from (-1000, -1000) to (1000, 1000).
        // UI coordinates range from (0, 0) to (width, height).
        matrix.postScale(mSurfaceView.getWidth() / 2000f, mSurfaceView.getHeight() / 2000f);
        matrix.postTranslate(mSurfaceView.getWidth() / 2f, mSurfaceView.getHeight() / 2f);

        ArrayList rectList = new ArrayList<RectF>();
        for (Camera.Face face : faces) {
            RectF srcRect = new RectF(face.rect);
            RectF dstRect = new RectF(0f, 0f, 0f, 0f);
            matrix.mapRect(dstRect, srcRect);
            rectList.add(dstRect);
        }

        return rectList;
    }

}
